using Agron.Services.Proxies;

using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.Security.Permissions;
using System.Windows.Forms;


namespace Agron.UI.SmartClient
{
    /// <summary>
    /// The main <see cref="Form"/> of the application.
    /// </summary>
    partial class MainForm : Form
    {
        private const int RightMargin = 150;
        
        private static bool? _isWindowsXpOrAbove;
        private static readonly object _lockObject = new object();

        private bool _doClose;
        private bool _isMouseDown;
        private Point _downLocation;
        private Point _downMousePosition;

        /// <summary>
        /// Initializes a new instance of the <see cref="MainForm"/> class.
        /// </summary>
        public MainForm()
        {
            this.InitializeComponent();
            this.SetAnonymousMethods();
            this.PositionForm();

        }

        /// <summary>
        /// Gets a value indicating whether the current operating system is Windows XP or above.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if the current operating system is Windows XP or above; otherwise, <c>false</c>.
        /// </value>
        public static bool IsWindowsXpOrAbove
        {
            get
            {
                if (null == _isWindowsXpOrAbove)
                {
                    OperatingSystem os = Environment.OSVersion;
                    bool runningNT = (PlatformID.Win32NT == os.Platform);

                    MainForm._isWindowsXpOrAbove = runningNT && (0 <= os.Version.CompareTo(new Version(5, 1, 0, 0)));
                }

                return _isWindowsXpOrAbove.Value;
            }
        }

        /// <summary>
        /// Gets an overridden version of the CreateParams property that contains the required creation parameters for when the control handle is created.
        /// </summary>
        /// <value>
        /// An overriden version of the <see cref="CreateParams"/> property that contains the required creation parameters for when the control handle is created.
        /// </value>
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams parameters = base.CreateParams;

                if (MainForm.IsWindowsXpOrAbove)
                    parameters.ClassStyle = (parameters.ClassStyle | Constants.CS_DROPSHADOW);

                return parameters;
            }
        }

        /// <summary>
        /// Displays a modal dialog by instantianting a new instance of the specified <typeparamref name="TDialog"/>/
        /// </summary>
        /// <typeparam name="TDialog">A dialog that implements <see cref="DialogBase"/>.</typeparam>
        internal void ProcessModalDialog<TDialog>() where TDialog : DialogBase, new()
        {
            using (TDialog dialog = new TDialog())
            {
                dialog.ShowDialog(this);
            }
        }

        /// <summary>
        /// Attaches anonymous methods to some of the menus.
        /// </summary>
        private void SetAnonymousMethods()
        {
            this.editContactInfoToolStripMenuItem.Click += delegate { this.ProcessModalDialog<EditUserInfoForm>(); };
            this.hideToolbarToolStripMenuItem.Click += delegate { this.Close(); };
            this.hideToolStripButton.Click += delegate { this.Close(); };
            this.restoreToolStripMenuItem.Click += delegate { this.notifyIcon_MouseDoubleClick(this, null); };
            this.helpToolStripButton.Click += delegate { Process.Start(string.Format(CultureInfo.InvariantCulture, "{0}/Forms/Faq.aspx", Properties.Settings.Default.WebsiteUrl)); };
            this.calendarToolStripMenuItem.Click += delegate { this.DisplayCalendarDialog(); };
            this.scheduleToolStripButton.Click += delegate { this.DisplayCalendarDialog(); };
            this.scheduleSessionToolStripMenuItem.Click += delegate { this.ProcessModalDialog<EditSessionForm>(); };
            this.Load += delegate { this.internetAddressBackgroundWorker.RunWorkerAsync(); };
            this.startToolStripButton.Click += delegate { this.ProcessModalDialog<StartSessionForm>(); };
            this.startToolStripMenuItem.Click += delegate { this.ProcessModalDialog<StartSessionForm>(); };
        }

        /// <summary>
        /// Positions the <see cref="MainForm"/> either by using the last know position or by positioning the form on the top right of the <see cref="Screen.PrimaryScreen"/>.
        /// </summary>
        private void PositionForm()
        {
            Screen primaryScreen = Screen.PrimaryScreen;

            base.Top = primaryScreen.WorkingArea.Top;
            base.Left = primaryScreen.WorkingArea.Width - base.Width - MainForm.RightMargin;
        }

        /// <summary>
        /// Handles the MouseDoubleClick event of the notifyIcon control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
        private void notifyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            base.ShowInTaskbar = true;
            base.Visible = true;
            this.PositionForm();

            this.notifyIcon.Visible = false;
        }

        /// <summary>
        /// Handles the FormClosing event of the MainForm <see cref="Form"/>.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.FormClosingEventArgs"/> instance containing the event data.</param>
        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (!this._doClose)
            {
                e.Cancel = true;

                this.notifyIcon.Visible = true;

                this.ShowInTaskbar = false;
                this.Hide();

                if (!Properties.Settings.Default.TrayInfoDisplayed)
                {
                    this.notifyIcon.ShowBalloonTip(
                        /*timeout*/ 0,
                        /*title*/ Properties.Resources.MainFormNotifyIconAgronIsStillRunningTitle,
                        /*text*/ Properties.Resources.MainFormNotifyIconAgronIsStillRunningMessage,
                        /*tipIcon*/ ToolTipIcon.Info);
                }
            }
            else
            {
                Application.Exit();
            }
        }

        /// <summary>
        /// Handles the Click event of the exitToolStripMenuItem and the trayExitToolStripMenuItem controls.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this._doClose = true;
            this.Close();
        }

        /// <summary>
        /// Handles the BalloonTipClicked event of the notifyIcon control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        private void notifyIcon_BalloonTipClicked(object sender, EventArgs e)
        {
            try
            {
                Properties.Settings.Default.TrayInfoDisplayed = true;
                Properties.Settings.Default.Save();
            }
            catch (SystemException exception)
            {
                ExceptionPolicy.HandleException(exception, Constants.SmartClientExceptionPolicy);
                MessageBoxService.ReportError(this, Properties.Resources.MainFormSaveSettingsFailed);
            }
        }

        /// <summary>
        /// Handles the MouseMove event of the titleLabel control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.MouseEventArgs"/> instance containing the event data.</param>
        private void titleLabel_MouseMove(object sender, MouseEventArgs e)
        {
            lock (_lockObject)
            {
                if (MouseButtons.Left == e.Button)
                {
                    if (_isMouseDown)
                    {
                        Point mousePosition = Form.MousePosition;

                        Point location = _downLocation;
                        location.X = (location.X + (mousePosition.X - _downMousePosition.X));
                        location.Y = (location.Y + (mousePosition.Y - _downMousePosition.Y));
                        base.Location = location;
                    }
                    else
                    {
                        _downLocation = base.Location;
                        _downMousePosition = Form.MousePosition;
                        _isMouseDown = true;
                    }
                }
                else
                {
                    _isMouseDown = false;
                }

                base.OnMouseMove(e);
            }
        }

        private void DisplayCalendarDialog()
        {
            using (CalendarForm calendarForm = new CalendarForm())
            {
                calendarForm.ShowDialog(this);
            }
        }

        /// <summary>
        /// Handles the DoWork event of the internetAddressBackgroundWorker control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.DoWorkEventArgs"/> instance containing the event data.</param>
        private void internetAddressBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            string serviceUrl = string.Format(CultureInfo.InvariantCulture, "{0}/Services/AddressInfoService.asmx", Properties.Settings.Default.WebsiteUrl);

            using (AddressInfoServiceProxy serviceProxy = new AddressInfoServiceProxy(serviceUrl))
            {
                e.Result = serviceProxy.GetIPAddress();
            }
        }

        /// <summary>
        /// Handles the RunWorkerCompleted event of the internetAddressBackgroundWorker control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.RunWorkerCompletedEventArgs"/> instance containing the event data.</param>
        private void internetAddressBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (null == e.Error)
            {
                System.Net.IPAddress address;
                string result = (e.Result as string);

                if (!System.Net.IPAddress.TryParse(result, out address))
                    MessageBoxService.ReportError(this, Properties.Resources.MainFormIPAddressRetrieveFailed);

                //SessionInfo.InternetIPAddress = result;
            }
            else
            {
                MessageBoxService.ReportError(this, Properties.Resources.MainFormIPAddressRetrieveFailed);
            }
        }
    }
}